package com.xiashitech.agent.utils;

import org.jetbrains.annotations.NotNull;

import java.lang.reflect.Field;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

import static cn.hutool.core.util.ObjectUtil.isBasicType;

public class ObjectFieldUtil {
    public static int curJ = 1;

    public static <T> void replaceObjectFieldValue(@NotNull Object o, @NotNull Class<T> fieldClass, String fieldName, String regex, String replaceSymbol, int deep) {
        if (deep < 1) {
            //超出深度，不再执行该深度的属性值替换
            return;
        }
        //获取属性值
        Field[] declaredFields = o.getClass().getDeclaredFields();
        try {
            //遍历属性
            for (Field declaredField : declaredFields) {
                //设置为可编辑
                declaredField.setAccessible(true);
                //获取属性值
                Object value = declaredField.get(o);
                if (List.class.equals(declaredField.getType())) {
                    if (value == null) {
                        continue;
                    }

                    //是个列表，遍历替换
                    for (Object item : (List) value) {
                        //可探深度减小
                        replaceObjectFieldValue(item, fieldClass, fieldName, regex, replaceSymbol, deep - 1);
                    }
                } else if (fieldClass.equals(declaredField.getType())) {
                    //是目标属性类型
                    //判断是不是目标属性名
                    if (!(fieldName == null || fieldName.equals(declaredField.getName()))) {
                        //非目标属性名，执行下一个
                        continue;
                    }
                    boolean flag = isBasicType(value);

                    String newValue = String.valueOf(value).replaceAll(regex, replaceSymbol);
                    declaredField.set(o, newValue);

                    //判断是否为需替换的目标值
                 /*   if (Objects.equals(oldValue, value)) {
                        //执行替换
                        declaredField.set(o, newValue);
                    }*/
                } else {
                    if (value == null) {
                        continue;
                    }
                    //是否非基础数据类型
                    if (!isBasicType(value)) {
                        //更深一层执行，可探深度减少
                        replaceObjectFieldValue(value, fieldClass, fieldName, regex, replaceSymbol, deep - 1);
                    }
                }
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }


    public static <T> int getRecordSize(@NotNull Object o, int targetDeep, int currentDeep, int index) {

        if (targetDeep <= 1) {
            if (o instanceof List) {
                return ((List) o).size();
            } else {
                return 1;
            }
        } else if (targetDeep > 1 && targetDeep<=10) {
            //获取属性值
            Field[] declaredFields = o.getClass().getDeclaredFields();
            int i = 0;
            try {
                //遍历属性
                for (Field declaredField : declaredFields) {
                    declaredField.setAccessible(true);
                    //获取属性值
                    Object value = declaredField.get(o);
                    if (currentDeep < targetDeep) {
                        getRecordSize(value, targetDeep, currentDeep + 1, index);
                    }
                    if (List.class.equals(declaredField.getType())) {
                        if (value == null) {
                            continue;
                        }
                        if (i >= index) {
                            return ((List) value).size();
                        }
                    }
                    else {
                        if (i >= index) {
                            return -2;
                        }
                    }
                    i++;
                }

            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }

        }
        else if(targetDeep>10)
        {
            if (o instanceof List) {
                return ((List) o).size();
            }
            Field[] declaredFields = o.getClass().getDeclaredFields();
            int i = 0;
            try {
                //遍历属性
                for (Field declaredField : declaredFields) {
                    declaredField.setAccessible(true);
                    //获取属性值
                    Object value = declaredField.get(o);
                    if (List.class.equals(declaredField.getType())) {
                        if (value == null) {
                            continue;
                        }
                            return ((List) value).size();
                    }
                    else {
                        if (value == null) {
                            continue;
                        }
                        if(targetDeep<=currentDeep)
                        {
                            return 1;
                        }
                        if (!isBasicType(value)) {
                            getRecordSize(value,targetDeep,currentDeep+1,0);
                        }
                    }
                }

            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return 1;
    }

    public static boolean isBasicType(Object o) {
        if (o == null) {
            return false;
        } else {
            return o instanceof Integer || o instanceof String || o instanceof Short || o instanceof Long || o instanceof Character || o instanceof Byte || o instanceof Boolean || o instanceof BigInteger || o.getClass().getPackage() != null && o.getClass().getPackage().getName().equals("java.math");
        }
    }
    public static Object printObjectFields(Object obj,String prefix) throws IllegalAccessException {
        System.out.println(prefix+" start printObjectFields obj value "+JsonUtil.convertObjectToString(obj));
        Class<?> clazz = obj.getClass();
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            if(isBasicType(field.get(obj)))
            {
                System.out.println(prefix+" printObjectFields key: "+field.getName() + " value:  " + field.get(obj));
            }
            else {
                System.out.println(prefix+" ----obj next level---- ");
                printObjectFields(field.get(obj),prefix);
            }

        }
        return obj;
    }
}

